package com.stars.distributed.schedule.util;

import com.stars.distributed.schedule.constant.DistributedScheduleConstants;
import com.stars.distributed.schedule.bean.DbScheduleServer;
import com.stars.distributed.schedule.enums.Switch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * 用于读取分布式调度框架属性文件的工具类
 *
 * @author guoguifang
 */
public class DistributedSchedulePropertiesUtil {

    private static final Logger logger = LoggerFactory.getLogger(DistributedSchedulePropertiesUtil.class);

    private static final String DISTRIBUTED_PROPERTIES = "dbschedule.properties";

    private static final String DISTRIBUTED_BUILD_PROPERTIES = "dbschedule-build.properties";

    private static final String DISTRIBUTED_SCHEDULE_ENABLED = "distributed.schedule.enabled";

    private static final String DISTRIBUTED_SCHEDULE_SERVER_ID = "distributed.schedule.serverId";

    private static final String DISTRIBUTED_SCHEDULE_SCHEDULE_SWITCH = "distributed.schedule.scheduleSwitch";

    private static final String DISTRIBUTED_SCHEDULE_CORE_POOL_SIZE = "distributed.schedule.corePoolSize";

    private static final String DISTRIBUTED_SCHEDULE_MAX_POOL_SIZE = "distributed.schedule.maxPoolSize";

    private static final String DISTRIBUTED_SCHEDULE_KEEP_ALIVE_TIME = "distributed.schedule.keepAliveTime";

    private static final String DISTRIBUTED_SCHEDULE_START_DELAY_TIME = "distributed.schedule.startDelayTime";

    private static final String VERSION;

    private static final Integer VERSION_ITERATION;

    /**
     * 获取本地配置对象：
     * 1.获取本地分布式调度框架的属性文件
     * 2.封装为本地配置对象
     * 2.1 如果本地属性文件不存在则本地配置对象的属性全部设置为默认值
     * 2.2 如果本地属性文件存在但有错误的配置时只把错误的属性设置为默认值
     */
    public static DbScheduleServer encapsulateLocalDistributedScheduleServerConfig() {
        DbScheduleServer localDbScheduleServerConfig = new DbScheduleServer();
        Properties properties = getProperties(DISTRIBUTED_PROPERTIES, true);
        String enabled, serverId, scheduleSwitch, corePoolSize, maxPoolSize, keepAliveTime, startDelayTime;
        if (properties != null && (enabled = properties.getProperty(DISTRIBUTED_SCHEDULE_ENABLED)) != null) {
            localDbScheduleServerConfig.setEnabled(Boolean.parseBoolean(enabled));
        } else {
            localDbScheduleServerConfig.setEnabled(Boolean.parseBoolean(PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_ENABLED, "true")));
        }
        if (properties != null && (serverId = properties.getProperty(DISTRIBUTED_SCHEDULE_SERVER_ID)) != null && StringUtils.isNotBlank(serverId)) {
            localDbScheduleServerConfig.setServerId(serverId);
        } else {
            if (StringUtils.isNotBlank((serverId = PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_SERVER_ID, "")))) {
                localDbScheduleServerConfig.setServerId(serverId);
            }
        }
        if (properties != null && (scheduleSwitch = properties.getProperty(DISTRIBUTED_SCHEDULE_SCHEDULE_SWITCH)) != null && Switch.forCode(scheduleSwitch) == Switch.CLOSE) {
            localDbScheduleServerConfig.setScheduleSwitch(scheduleSwitch);
        } else {
            localDbScheduleServerConfig.setScheduleSwitch(PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_SCHEDULE_SWITCH, Switch.OPEN.getCode()));
        }
        if (properties != null && (corePoolSize = properties.getProperty(DISTRIBUTED_SCHEDULE_CORE_POOL_SIZE)) != null && StringUtils.isNumeric(corePoolSize)) {
            localDbScheduleServerConfig.setCorePoolSize(Integer.parseInt(corePoolSize) > 0 ? Integer.parseInt(corePoolSize) : 1);
        } else {
            if (StringUtils.isNumeric((corePoolSize = PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_CORE_POOL_SIZE, "")))) {
                localDbScheduleServerConfig.setCorePoolSize(Integer.parseInt(corePoolSize) > 0 ? Integer.parseInt(corePoolSize) : 1);
            }
        }
        if (properties != null && (maxPoolSize = properties.getProperty(DISTRIBUTED_SCHEDULE_MAX_POOL_SIZE)) != null && StringUtils.isNumeric(maxPoolSize)) {
            localDbScheduleServerConfig.setMaxPoolSize(Integer.parseInt(maxPoolSize) > 0 ? Integer.parseInt(maxPoolSize) : 1);
        } else {
            if (StringUtils.isNumeric((maxPoolSize = PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_MAX_POOL_SIZE, "")))) {
                localDbScheduleServerConfig.setMaxPoolSize(Integer.parseInt(maxPoolSize) > 0 ? Integer.parseInt(maxPoolSize) : 1);
            }
        }
        if (localDbScheduleServerConfig.getCorePoolSize() > localDbScheduleServerConfig.getMaxPoolSize()) {
            localDbScheduleServerConfig.setMaxPoolSize(localDbScheduleServerConfig.getCorePoolSize());
        }
        if (properties != null && (keepAliveTime = properties.getProperty(DISTRIBUTED_SCHEDULE_KEEP_ALIVE_TIME)) != null) {
            localDbScheduleServerConfig.setKeepAliveTime(keepAliveTime);
        } else {
            localDbScheduleServerConfig.setKeepAliveTime(PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_KEEP_ALIVE_TIME, DistributedScheduleConstants.DEFAULT_KEEP_ALIVE_TIME));
        }
        if (properties != null && (startDelayTime = properties.getProperty(DISTRIBUTED_SCHEDULE_START_DELAY_TIME)) != null) {
            localDbScheduleServerConfig.setStartDelayTime(startDelayTime);
        } else {
            localDbScheduleServerConfig.setStartDelayTime(PropertyPlaceholderUtil.replace(DISTRIBUTED_SCHEDULE_START_DELAY_TIME, DistributedScheduleConstants.DEFAULT_START_DELAY_TIME));
        }
        return localDbScheduleServerConfig;
    }

    public static String getVersion() {
        return VERSION;
    }

    public static Integer getVersionIteration() {
        return VERSION_ITERATION;
    }

    private static Properties getProperties(String name, boolean root) {
        InputStream inputStream = null;
        try {
            if (root) {
                try {
                    inputStream = DistributedSchedulePropertiesUtil.class.getClassLoader().getResourceAsStream(name);
                } catch (Exception e) {
                    inputStream = DistributedSchedulePropertiesUtil.class.getResourceAsStream(name);
                }
            } else {
                inputStream = DistributedSchedulePropertiesUtil.class.getResourceAsStream(name);
            }
            if (inputStream != null) {
                Properties properties = new Properties();
                properties.load(inputStream);
                return properties;
            }
        } catch (Exception e) {
            if (logger.isWarnEnabled()) {
                logger.warn("Load " + name + " file failure!", e);
            }
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Close inputStream failure!", e);
                    }
                }
            }
        }
        return null;
    }

    static {
        Properties props = getProperties(DISTRIBUTED_BUILD_PROPERTIES, false);
        if (props == null) {
            logger.error("Get distributed schedule version and versionIteration fail in " + DISTRIBUTED_BUILD_PROPERTIES + "!");
            System.exit(1);
        }
        VERSION = props.getProperty("distributed.schedule.version");
        VERSION_ITERATION = Integer.valueOf(props.getProperty("distributed.schedule.versionIteration"));
    }

}
